﻿using System;
using System.Collections.Generic;

namespace XCSerialPort
{
    public class SerialPort_Usb_I2CManager : ISerialPortManager
    {
        private const int DEVICE_NOT_FOUND = -1; // 设备未找到常量
        private int deviceCount = 0; // 设备数量
        private int currentDeviceIndex = 0; // 当前选择的设备索引
        private uint deviceID = 0; // 当前设备 ID
        public bool IsUsbOpen { get; private set; } // 设备打开状态

        public SerialPort_Usb_I2CManager() { }

        public SerialPort_Usb_I2CManager(int _currentDeviceIndex, uint _deviceID)
        {
            IsUsbOpen = false;
            deviceID = _deviceID;
            currentDeviceIndex = _currentDeviceIndex;
        }

        public void SetDeviceConfig(int _currentDeviceIndex, uint _deviceID)
        {
            deviceID = _deviceID;
            currentDeviceIndex = _currentDeviceIndex;
        }

        /// <summary>
        /// 关闭当前打开的 USB 设备。
        /// </summary>
        /// <param name="msg">状态消息。</param>
        public void Close(out string msg)
        {
            if (XChipUSB.UsbDestroyUSB())
            {
                IsUsbOpen = false; // 更新状态
                msg = "设备已关闭成功。";
            }
            else
            {
                msg = "关闭设备失败。";
            }
        }

        /// <summary>
        /// 获取连接的所有串口设备名称。
        /// </summary>
        /// <param name="msg">状态消息。</param>
        /// <returns>串口名称列表。</returns>
        public string[] GetSerialPorts(out string msg)
        {
            List<string> serialPorts = new List<string>();

            // 初始化 USB 设备
            XChipUSB.UsbIniDevice();
            XChipUSB.UsbUpdateDevice();

            // 获取 USB 设备的数量
            deviceCount = XChipUSB.UsbGetDeviceNum();
            if (deviceCount < 0)
            {
                msg = "获取设备数量失败。";
                return Array.Empty<string>();
            }

            // 获取所有设备信息
            DeviceInfos[] deviceInfoArray = XChipUSB.UsbGetAllDeviceInfoViaMultiplex(deviceCount);

            foreach (var device in deviceInfoArray)
            {
                // 检查 VID 和 PID 是否有效
                if (!string.IsNullOrEmpty(device.VID) && !string.IsNullOrEmpty(device.PID))
                {
                    serialPorts.Add(device.DeviceName); //  DeviceName 是串口名称
                }
            }

            msg = $"找到 {serialPorts.Count} 个设备。";
            return serialPorts.ToArray();
        }

        /// <summary>
        /// 打开指定的 USB 设备。
        /// </summary>
        /// <param name="msg">状态消息。</param>
        /// <returns>是否成功打开设备。</returns>
        public bool Open(out string msg)
        {
            XChipUSB.UsbIniDevice();
            XChipUSB.UsbUpdateDevice();

            IsUsbOpen = XChipUSB.UsbSelectDevice(currentDeviceIndex);

            if (IsUsbOpen)
            {
                msg = "设备已打开。";
                return true;
            }
            else
            {
                msg = "打开设备失败。";
                return false;
            }
        }

        /// <summary>
        /// 从指定地址读取数据。
        /// </summary>
        /// <param name="addr">要读取的地址。</param>
        /// <param name="msg">状态消息。</param>
        /// <param name="length">要读取的数据长度（默认为 1）。</param>
        /// <param name="timeoutMilliseconds">超时时间（毫秒，默认为 150）。</param>
        /// <returns>读取到的值列表。</returns>
        public List<ulong> ReadRegister(ulong addr, out string msg, int length = 1, int timeoutMilliseconds = 150)
        {
            List<ulong> values = new List<ulong>();
            msg = "读取成功"; // 默认成功消息

            // 检查 deviceID 是否有效
            if (deviceID == 0)  // 0 是无效 ID，您可以根据实际情况调整
            {
                msg = "无效的设备 ID。";
                return null;
            }

            // 循环读取指定数量的数据
            for (int i = 0; i < length; i++)
            {
                uint readValue = 0; // 读取的数据值
                bool readSuccess = XChipUSB.UsbI2CBulkRead((uint)(addr + (ulong)i), new uint[] { readValue }, 1, deviceID);

                if (readSuccess)
                {
                    values.Add(readValue); // 存储读取到的值
                    msg += $"\nR: 0x{addr + (ulong)i:X8}, 0x{readValue:X2}";
                }
                else
                {
                    msg = $"地址 0x{addr + (ulong)i:X} 读取失败";
                    return null; // 读取失败，返回 null
                }
            }

            return values; // 返回读取到的所有值
        }

        /// <summary>
        /// 向指定地址写入数据。
        /// </summary>
        /// <param name="addr">要写入的地址。</param>
        /// <param name="value">要写入的值列表。</param>
        /// <param name="msg">状态消息。</param>
        /// <param name="length">写入的长度（默认为 1）。</param>
        /// <param name="timeoutMilliseconds">超时时间（毫秒，默认为 150）。</param>
        public void WriteRegister(ulong addr, List<ulong> value, out string msg, int length = 1, int timeoutMilliseconds = 150)
        {
            msg = "写入成功"; // 默认成功消息

            // 检查 deviceID 是否有效
            if (deviceID == 0)  // 假设 0 是无效 ID，您可以根据实际情况调整
            {
                msg = "无效的设备 ID。";
                return;
            }

            // 检查输入值的数量是否与长度一致
            if (value.Count != length)
            {
                msg = "要写入的值数量与指定长度不一致";
                return;
            }

            // 循环写入指定数量的数据
            for (int i = 0; i < length; i++)
            {
                uint writeValue = (uint)value[i]; // 要写入的值
                bool writeSuccess = XChipUSB.UsbI2CBulkWrite((uint)(addr + (ulong)i), new uint[] { writeValue }, 1, deviceID);

                if (!writeSuccess)
                {
                    msg = $"地址 0x{addr + (ulong)i:X} 写入失败";
                    return; // 写入失败，返回
                }
                // 更新消息以包含写入的地址和值
                msg += $"\nW: 0x{addr + (ulong)i:X8}, 0x{writeValue:X2}";
            }
        }
        public bool DeviceStatus()
        {
            return IsUsbOpen;
        }

        public void SetDeviceConfig(int _Index)
        {
            throw new NotImplementedException();
        }
    }
}
